﻿using System.Data.Common;
using System.Diagnostics;
using Tetris.Game.Common.TetrisCenter;
using Tetris.Game.Common.TetrisCenter.TetrisBase;
using Tetris.Game.ControlsBase;
using Tetris.Game.ControlsBase.Common;

namespace Tetris.Game.Common.Algorithm
{
    public unsafe class TetrisAI : IAlgorithm
    {
        private readonly int Width = 10;
        private readonly int Height = 20;
        public TetrisAI(int width = 10, int height = 20)
        {
            Width = width;
            Height = height;
        }
        public ChooseBestMoveResult ChooseBestMove(BlockShapeBase piece, BlockControl[,] grid)
        {
            var tempGrid = grid.DeepCloneBlockControlArray();
            int bestScore = int.MinValue;
            int bestX = 0;
            int bestY = 0;
            int bestRotation = 0;
            BlockShapeBase? testPiece = CreationBlockShapeCallback(piece.TetrisShapeType, false);
            testPiece.Move(tempGrid, DirectionType.Down);
            for (int rotation = 0; rotation < 4; rotation++)
            {
                int dx = 0;
                while (testPiece.Move(tempGrid, DirectionType.Right))
                {
                    ++dx;
                    int dy = tempGrid.DropHeight(testPiece);
                    int score = EvaluatePosition(testPiece, tempGrid);
                    testPiece.Move(tempGrid, 0, -dy);// 重置位置
                    if (score > bestScore)
                    {
                        bestScore = score;
                        bestX = dx;
                        bestRotation = rotation;
                    }
                }
                testPiece.Move(tempGrid, -dx + 1, 0);// 重置位置
                dx = 0;
                while (testPiece.Move(tempGrid, DirectionType.Left))
                {
                    ++dx;
                    int dy = tempGrid.DropHeight(testPiece);
                    int score = EvaluatePosition(testPiece, tempGrid);
                    testPiece.Move(tempGrid, 0, -dy);// 重置位置
                    if (score > bestScore)
                    {
                        bestScore = score;
                        bestX = -dx;
                        bestRotation = rotation;
                    }
                }

               bool a= testPiece.RotateShape(tempGrid);// 旋转
            }

            testPiece.Dispose();
            for (int i = 0; i < tempGrid.GetLength(0); i++)
            {
                for (int j = 0; j < tempGrid.GetLength(1); j++)
                {
                    BlockControl originalBlockControl = tempGrid[i, j];
                    if (originalBlockControl != null)
                    {
                        originalBlockControl.ExecBeginInvoke(() =>
                        {
                            originalBlockControl.Dispose();
                            originalBlockControl = null;
                        });
                    }
                }
            }
            return new ChooseBestMoveResult
            {
                BestScore = bestScore,
                BestX = bestX,
                Rotation = bestRotation
            };
        }
        public Func<ShapeType, bool, BlockShapeBase?>? CreationBlockShapeCallback { get; set; }
        /// <summary>
        /// 计算得分
        /// </summary>
        /// <param name="piece"></param>
        /// <param name="grid"></param>
        /// <returns></returns>
        private int EvaluatePosition(BlockShapeBase piece, BlockControl[,] grid)
        {
            MergePieceToGrid(piece, grid);

            int score = 0;
            score += CountCompleteLines(grid) * 100; // High reward for clearing lines
            score -= CalculateHoles(grid) * 50; // Increased penalty for creating holes
            score -= CalculateCumulativeHeights(grid) * 2; // Smaller penalty for height
            score -= CalculateBumpiness(grid) * 5; // Penalty for bumpiness
            score -= CalculateLowestHoleHeight(grid) * 10; // Penalty for the height of the lowest hole
            score += CalculateGridSmoothness(grid) * 5; // Reward for grid smoothness

            return score;
        }
        private int CalculateLowestHoleHeight(BlockControl[,] grid)
        {
            int lowestHoleHeight = Height;
            for (int x = 0; x < Width; x++)
            {
                for (int y = Height - 1; y >= 0; y--)
                {
                    if (grid[y, x] == null && (y == Height - 1 || grid[y + 1, x] != null))
                    {
                        if (y < lowestHoleHeight)
                        {
                            lowestHoleHeight = y;
                        }
                        break;
                    }
                }
            }
            return Height - lowestHoleHeight;
        }

        private int CalculateGridSmoothness(BlockControl[,] grid)
        {
            int smoothness = 0;
            for (int x = 0; x < Width - 1; x++)
            {
                int columnHeight = CalculateColumnHeight(grid, x);
                int nextColumnHeight = CalculateColumnHeight(grid, x + 1);
                smoothness += Math.Abs(columnHeight - nextColumnHeight);
            }
            return smoothness;
        }

        private int CalculateColumnHeight(BlockControl[,] grid, int x)
        {
            for (int y = 0; y < Height; y++)
            {
                if (grid[y, x] != null)
                {
                    return Height - y;
                }
            }
            return 0;
        }
        /// <summary>
        /// 将饼图合并到网格
        /// </summary>
        /// <param name="piece"></param>
        /// <param name="grid"></param>
        private void MergePieceToGrid(BlockShapeBase piece, BlockControl[,] grid)
        {
            fixed (BlockControl* block = piece.BlockControls, set = grid)
            {
                for (int i = 0; i < piece.BlockControls.Length; i++)
                {
                    BlockControl* cur = block + i;
                    *(set + cur->PositionY * Width + cur->PositionX) = *cur;
                }
            }
        }
        #region 计算
        /// <summary>
        /// 计数完整行
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        private int CountCompleteLines(BlockControl[,] grid)
        {
            int completeLines = 0;
            for (int y = 0; y < Height; y++)
            {
                bool isComplete = true;
                for (int x = 0; x < Width; x++)
                {
                    if (grid[y, x] == null)
                    {
                        isComplete = false;
                        break;
                    }
                }
                if (isComplete)
                {
                    completeLines++;
                }
            }
            return completeLines;
        }
        /// <summary>
        /// 计算孔
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        private int CalculateHoles(BlockControl[,] grid)
        {
            int holes = 0;
            for (int x = 0; x < Width; x++)
            {
                bool blockFound = false;
                for (int y = 0; y < Height; y++)
                {
                    if (grid[y, x] != null)
                    {
                        blockFound = true;
                    }
                    else if (blockFound && grid[y, x] == null)
                    {
                        holes++;
                    }
                }
            }
            return holes;
        }
        /// <summary>
        /// 计算累计高度
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        private int CalculateCumulativeHeights(BlockControl[,] grid)
        {
            int totalHeight = 0;
            for (int x = 0; x < Width; x++)
            {
                for (int y = 0; y < Height; y++)
                {
                    if (grid[y, x] != null)
                    {
                        totalHeight += (Height - y);
                        break;
                    }
                }
            }
            return totalHeight;
        }
        /// <summary>
        /// 计算凹凸
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        private int CalculateBumpiness(BlockControl[,] grid)
        {
            int bumpiness = 0;
            int lastHeight = 0;
            int currentHeight;
            for (int x = 0; x < Width; x++)
            {
                currentHeight = 0;
                for (int y = 0; y < Height; y++)
                {
                    if (grid[y, x] != null)
                    {
                        currentHeight = Height - y;
                        break;
                    }
                }
                if (x > 0)
                {
                    bumpiness += Math.Abs(currentHeight - lastHeight);
                }
            }
            return bumpiness;
        }
        #endregion
    }
}
